package cn.admin.remoting;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;

public abstract class ClientManager {

    private static final ClientManager instance;

    public abstract Client get(String appName, String targetUrl,
                               InetSocketAddress localAddress,List<IOEventListener> listeners,
                               Map<Class<?>,RequestProcessor<?>> processors) throws RemotingException,InterruptedException;

    public final Client get(String appName, String targetUrl, List<IOEventListener> listeners,
                            Map<Class<?>,RequestProcessor<?>> processors) throws RemotingException,InterruptedException {
        return this.get(appName,targetUrl,null,listeners,processors);
    }

    public final Client get(String appName,String targetUrl) throws RemotingException,
            InterruptedException {
        return this.get(appName,targetUrl,null,null);
    }

    public abstract ClientFuture getAsync(String appName,String targetUrl,
                                          InetSocketAddress localAddress,
                                          List<IOEventListener> listeners,Map<Class<?>,
            RequestProcessor<?>> processors);

    public final ClientFuture getAsync(String appName,String targetUrl,
                                        List<IOEventListener> listeners,Map<Class<?>,
            RequestProcessor<?>> processors) {
        return this.getAsync(appName,targetUrl,null,listeners,processors);
    }

    public final ClientFuture getAsync(String appName,String targetUrl) throws RemotingException,InterruptedException{
        return this.getAsync(appName,targetUrl,null,null);
    }

    public abstract void closeEnsureNoReconnect(String appName,String targetUrl);

    public abstract void closeAllClients(String appName);

    public abstract ConnectionFactory getConnectionFactory(String appName);

    public static ClientManager getImpl() {
        return instance;
    }

    static {
        String implyClassName = "cn.admin.remoting.impl.DefaultClientManager";
        try {
            instance = (ClientManager) Class.forName(implyClassName).newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("创建ClientManager 实例失败.",e);
        }
    }

    public interface ClientFuture {

        String targetUrl();

        void cancel();

        boolean isDone();

        boolean isConnected();

        boolean isCancelled();

        Client get(long timeoutMs) throws RemotingException,InterruptedException;

    }

}
